-
Notifications
You must be signed in to change notification settings - Fork 4.6k
delegatingresolver: add default port to addresses #8613
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #8613 +/- ##
==========================================
- Coverage 82.00% 81.97% -0.03%
==========================================
Files 415 415
Lines 40697 40719 +22
==========================================
+ Hits 33372 33380 +8
- Misses 5937 5970 +33
+ Partials 1388 1369 -19
🚀 New features to boost your workflow:
|
addr, err := parseTarget(target.Endpoint()) | ||
if err != nil { | ||
return nil, fmt.Errorf("delegating_resolver: invalid target address %q: %v", target.Endpoint(), err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should guard this call to parseTarget
behind the feature flag since it can potentially lead to new/different failures after this PR is merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can have only one block guarded by the feature flag if we instead do the following:
addr := target.Endpoint()
if target.URL.Scheme == "dns" && !targetResolutionEnabled && envconfig.AddDefaultPort {
addr, err = parseTarget(target.Endpoint(), defaultPort)
if err != nil {
// return some error
}
}
This way we can use the parseTarget
function from the dns resolver without any modifications.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking was we should do the basic check and add localhost for all addresses if no host is present irrespective of the resolver being used, but adding default port 443 is only for DNS resolver with target resolution disabled. And the first part should not be behind the flag , but only 2nd part should. That is my understanding, let me know if I am missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my understanding, only the DNS resolver was defaulting the hostname to localhost
. Applying this logic to all resolvers would be a behaviour change which could potentially break some custom resolver that isn't expecting this. I would recommend avoiding such a change to be safe.
Also, since we're providing a env variable flag, we should ensure the flag can revert all (if not most) changes in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
internal/resolver/delegatingresolver/delegatingresolver_ext_test.go
Outdated
Show resolved
Hide resolved
name string | ||
target string | ||
wantConnectAddress string | ||
wantErrorSubstring string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add another test param for the env variable and tests cases for the env variable being disabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I already have a seperate test for it : TestDelegatingResolverEnvVarForDefaultPortDisable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we combine the tests using an additional param? That should help reduce duplicate code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
internal/resolver/delegatingresolver/delegatingresolver_ext_test.go
Outdated
Show resolved
Hide resolved
internal/resolver/delegatingresolver/delegatingresolver_ext_test.go
Outdated
Show resolved
Hide resolved
if target == "" { | ||
return "", fmt.Errorf("missing address") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this even possible since we already parse the target URI specified by the user in clientconn.go before we get here?
Ideally, it would be nicer to avoid checking conditions that are not possible, since it would simplify the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont see an explicit check for missing target in the clientconn.go and this is similar to the check we already have in dns.
// If the port field is empty (target ends with colon), e.g. "[::1]:", | ||
// this is an error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: I think it would be better to group these inline comments into a docstring for the function. That way, one can just read that docstring and get to know what the function is doing instead of reading it one piece at a time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
return "", fmt.Errorf("missing address") | ||
} | ||
if host, port, err := net.SplitHostPort(target); err == nil { | ||
if port == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the documentation of net.SplitHostPort
, the port
seems to be mandatory and it will return a missing port in address
error in that case. So, I don't think we could have err == nil
and port == ""
.
// SplitHostPort splits a network address of the form "host:port",
// "host%zone:port", "[host]:port" or "[host%zone]:port" into host or
// host%zone and port.
Please correct me if I'm wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err == nil
and port == ""
would be case where the target is something like : host:
i.e. they have the colon but no port specified after it.
disableDefaultPortEnvVar bool | ||
}{ | ||
{ | ||
name: "no port in target", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
if test.disableDefaultPortEnvVar { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you have to check this field? Why can't you set the value of the env var to the one specified by the test unconditionally? That way, the code will be immune to changes in the default value of the env var.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even I had thought of that, but idk why I decided to do it this way then. Changed.
} | ||
overrideTestHTTPSProxy(t, envProxyAddr) | ||
|
||
targetResolver := manual.NewBuilderWithScheme("dns") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you have to unregister the original dns
resolver and re-register it at the end of the test, for this test to not affect other tests?
targetResolver := manual.NewBuilderWithScheme("dns") | ||
target := targetResolver.Scheme() + ":///" + test.target | ||
// Set up a manual DNS resolver to control the proxy address resolution. | ||
proxyResolver, proxyResolverBuilt := setupDNS(t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see that this helper does re-register the original dns
resolver. But maybe this section can still be a little more explicit/readable etc. I'm not able to think of the exact way to make this better right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what we had earlier too..in the tests.
if test.wantErrorSubstring != "" { | ||
// Case 1: We expected an error. | ||
if err == nil { | ||
t.Fatalf("Delegating resolver created, want error containing %q", test.wantErrorSubstring) | ||
} | ||
if !strings.Contains(err.Error(), test.wantErrorSubstring) { | ||
t.Fatalf("Delegating resolver failed with error %v, want error containing %v", err.Error(), test.wantErrorSubstring) | ||
} | ||
return | ||
} | ||
|
||
// Case 2: We did NOT expect an error. | ||
if err != nil { | ||
t.Fatalf("Delegating resolver creation failed unexpectedly with error: %v", err) | ||
} | ||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) | ||
defer cancel() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test logic seems complicated enough to me that you can actually split the tests into two: go/gotip/episodes/50
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Fixes: #8607
RELEASE NOTES:
GRPC_EXPERIMENTAL_RESOLVER_ADD_DEFAULT_PORT
for adding a default port to addresses being sent to proxy which is set by default.